`ifndef _CASE2_SV
`define _CASE2_SV

class case2_sequence extends uvm_sequence #(transaction_dut);
    transaction_dut m_trans;
    rand int data_size = -1;
    rand int ntrans = 10;

    `uvm_object_utils(case2_sequence)
    function new(string name = "case2_sequence");
        super.new(name);
    endfunction

    constraint cstr{
        soft data_size inside {[4:3200]};
        soft ntrans inside {[5:100]};
    }

    virtual task body();
        `uvm_info("case2_sequence",  $sformatf("send %0d transaction to sequencer", ntrans), UVM_LOW)
        repeat(ntrans) begin	    
            `uvm_do_with(m_trans, { local::data_size > 0 -> pload.size() == local::data_size; } )
        end
        #1000;
    endtask
endclass

// -- virtual sequence for case2
class case2_vseq extends uvm_sequence;
	`uvm_object_utils(case2_vseq)
    `uvm_declare_p_sequencer(virtual_sequencer)

	function new(string name = "case2_vseq");
		super.new(name);
	endfunction
	virtual task body();
        case1_sequence dut_seq;
        uvm_status_e status;
        uvm_reg_data_t value;

        if(starting_phase != null)
            starting_phase.raise_objection(this);
        
        #1000;
        
        `uvm_do_on_with(dut_seq, p_sequencer.p_dut_sqr, {ntrans == 5; data_size == -1; })

        #10000;

        p_sequencer.p_rm.counter.read(status, value);
        `uvm_info("case2_vseq", $sformatf("after data transfer, reg_model counter's value is %0d", value), UVM_LOW);
        
        if(starting_phase != null)
            starting_phase.drop_objection(this);
    endtask
	
	
endclass

// -- virtual sequence for case2 register model
class case2_cfg_vseq extends uvm_sequence;
	`uvm_object_utils(case2_cfg_vseq)
    `uvm_declare_p_sequencer(virtual_sequencer)

	function new(string name = "case2_cfg_vseq");
		super.new(name);
	endfunction
	virtual task body();
        uvm_status_e status;
        uvm_reg_data_t value;

		if(starting_phase != null)
			starting_phase.raise_objection(this);
        
        #1000;

        p_sequencer.p_rm.invert.set(16'h1);
        value = p_sequencer.p_rm.invert.get();
        `uvm_info("case2_cfg_vseq", $sformatf("invert's desired value is %0h", value), UVM_LOW)
        
        value = p_sequencer.p_rm.invert.get_mirrored_value();
        `uvm_info("case2_cfg_vseq", $sformatf("invert's mirrored value is %0h", value), UVM_LOW)
        
        p_sequencer.p_rm.invert.update(status, UVM_FRONTDOOR);
        value = p_sequencer.p_rm.invert.get();
        `uvm_info("case2_cfg_vseq", $sformatf("invert's desired value is %0h", value), UVM_LOW)

        value = p_sequencer.p_rm.invert.get_mirrored_value();
        `uvm_info("case2_cfg_vseq", $sformatf("invert's mirrored value is %0h", value), UVM_LOW)
        p_sequencer.p_rm.invert.read(status, value);
        `uvm_info("case2_cfg_vseq", $sformatf("invert's actual value is %0h", value), UVM_LOW)
		
        #5000;
		if(starting_phase != null)
			starting_phase.drop_objection(this);
	endtask

endclass 


class case2 extends base_test;
    `uvm_component_utils(case2)
	function new(string name = "case2", uvm_component parent = null);
		super.new(name, parent);
	endfunction
	
	virtual function void build_phase(uvm_phase phase);
		super.build_phase(phase);
		
        /* 1. use default_sequence */
		uvm_config_db #(uvm_object_wrapper)::set(this, "v_sqr.configure_phase", "default_sequence", case2_cfg_vseq::type_id::get());
		uvm_config_db #(uvm_object_wrapper)::set(this, "v_sqr.main_phase", "default_sequence", case2_vseq::type_id::get());
	
    endfunction
	
endclass

`endif

 
